package com.bitBusy.manageyourriches.activity;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import android.app.ActionBar;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;

import com.bitBusy.manageyourriches.R;
import com.bitBusy.manageyourriches.database.contactClasses.PaymentMethod;
import com.bitBusy.manageyourriches.database.contactClasses.SpendingCategory;
import com.bitBusy.manageyourriches.database.contactClasses.SpendingSubcategory;
import com.bitBusy.manageyourriches.database.managers.DatabaseInteractor;
import com.bitBusy.manageyourriches.database.managers.DateTimeManager;
import com.bitBusy.manageyourriches.utilityClasses.adapters.BarPlotListAdapter;
import com.bitBusy.manageyourriches.utilityClasses.navigation.ActionBarChoice;
import com.bitBusy.manageyourriches.utilityClasses.pickers.DateChangeListener;

/**
 * Class that handles display of data in graph
 */
public class ViewGraphReportActivity extends FragmentActivity implements DateChangeListener 
{

	/** header titles*/
	/**private static final String[] HEADERSTRINGS = new String[]{"Category-wise spending", "Category specific spending", "Date-wise spending",
		"Year-wise spending", "Month-wise spending", "Day-wise spending", "Time-wise spending", 
						"Payment method-wise spending", "All subcategories-wise spending"};*/
	
	/** x axis choices*/
	private static final String[] XAXISSTRINGS = new String[]{"category", "subcategory", "date", "year","month","day", "time","payment method", 
									"all subcategories"};

		
	/** default spinner choice*/
	private static final int DEFAULTSPINNERCHOICE = 0;
		
	/** DBInteractor*/
	private DatabaseInteractor myDBInteractor;

	/**From date*/
	private String myFromDate;
	
	/**To date*/
	private String myToDate;

	/** map for category spending*/
	private LinkedHashMap<SpendingCategory, Double> myCategorySpending;
	
	/** map for each subcategory for every category*/
	private LinkedHashMap<String, LinkedHashMap<SpendingSubcategory, Double>> mySubcategorySpending;
	
	/**map for date spending*/
	private LinkedHashMap<String, Double> myDateSpending;
	
	/** map for year spending*/
	private LinkedHashMap<String, Double> myYearSpending;
	
	/** map for monthly spending*/
	private LinkedHashMap<String, Double> myMonthSpending;
	
	/** map for day spending*/
	private LinkedHashMap<String, Double> myDaySpending;
	
	/** map for time spending*/
	private LinkedHashMap<String, Double> myTimeSpending;
	
	/** map for payment method spending*/	
	private LinkedHashMap<PaymentMethod, Double> myPaymentMethodSpending;
	
	/** list of all spending categories*/
	private LinkedList<SpendingCategory> myCategories;
	
	/** list of all subcategories*/
	private LinkedHashMap<SpendingSubcategory, Double> myAllSubcategoriesSpending;
		   
	/** the list for graph plotting*/
	ListView myBarList;

	 
	/** current selection*/
	private int myCurrentSelection = 0;
	
	
    /** y axis values*/
   // private List<Number> myYAxisValues;
       
      @Override
    public void onCreate(Bundle savedInstanceState)
    {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_graph_report);
		myDBInteractor = new DatabaseInteractor(this);		

		ActionBar actionBar = getActionBar();
	    actionBar.setDisplayHomeAsUpEnabled(true);
	 
		myBarList = (ListView) findViewById(R.id.viewGraphReport_listView);
		setDateButtons();
        setupSpinners();
   		axisSpinnerHasBeenSet(myCurrentSelection);

        }
    
  
      /**Method to set date buttons*/
  	private void setDateButtons()
  	{
  		Button toDateButton = (Button) findViewById(R.id.viewGraphReport_toDateButton);
  		myToDate = DateTimeManager.getCurrentDate();
  		toDateButton.setText(myToDate);
  		
  		Button fromDateButton = (Button) findViewById(R.id.viewGraphReport_fromDateButton);
  		fromDateButton.setText(new StringBuilder().append(String.valueOf(DateTimeManager.getPreviousMonth())).append(myToDate.substring(myToDate.indexOf(DateTimeManager.DATESPLITTER))));
  		myFromDate = fromDateButton.getText().toString();

  		
  	}
  	
    /** method to setup spinners*/
    private void setupSpinners()
    {
    /*	Spinner headerSpinner = (Spinner) findViewById(R.id.viewGraphReport_xvsySpinner);
    	List<String> list = new ArrayList<String>();
    	
    	for (int i = 0; i < HEADERSTRINGS.length; i++)
    	{
    		list.add(HEADERSTRINGS[i]);
    	}
    	ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this,
    		android.R.layout.simple_spinner_item, list);
    	dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    	headerSpinner.setAdapter(dataAdapter);
    	*/
    	
    	Spinner xAxisSpinner = (Spinner) findViewById(R.id.viewGraphReport_xaxisSpinner);
    	List<String> xAxisList = new ArrayList<String>();
    	
    	for (int i = 0; i < XAXISSTRINGS.length; i++)
    	{
    		xAxisList.add(XAXISSTRINGS[i]);
    	} 
    	ArrayAdapter<String> xAxisDataAdapter = new ArrayAdapter<String>(this,
    			android.R.layout.simple_spinner_item, xAxisList);
    	xAxisDataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    	xAxisSpinner.setAdapter(xAxisDataAdapter);
    	
    /*	Spinner yAxisSpinner = (Spinner) findViewById(R.id.viewGraphReport_yaxisSpinner);
    	List<String> yAxisList = new ArrayList<String>();
    	for (int i = 0; i < YAXISSTRINGS.length; i++)
    	{
    		yAxisList.add(YAXISSTRINGS[i]);
    	}
    		ArrayAdapter<String> yAxisDataAdapter = new ArrayAdapter<String>(this,
    			android.R.layout.simple_spinner_item, yAxisList);
    	yAxisDataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    	yAxisSpinner.setAdapter(yAxisDataAdapter);*/
  
    	final Spinner categoriesSpinner = (Spinner) findViewById(R.id.viewGraphReport_categoriesSpinner);
    	List<SpendingCategory> categories = myDBInteractor.getAllSpendingCategories();
    	String[] categoryNames = new String[categories.size()];
    	if (categories != null)
    	{
    		int i = 0;
	    	for (SpendingCategory category: categories)
	    	{
	    		categoryNames[i] = category!=null?category.getName():null;
	    		i++;
	    	}
    	}
    		ArrayAdapter<String> categoriesAdapter = new ArrayAdapter<String>(this,
    			android.R.layout.simple_spinner_item, categoryNames);
    		categoriesAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    		categoriesSpinner.setAdapter(categoriesAdapter);
    	
    	
    	/*headerSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    		public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { 
    	    	Spinner xAxisSpinner = (Spinner) findViewById(R.id.viewGraphReport_xaxisSpinner);
    	    	if (xAxisSpinner.getSelectedItemPosition() != i)
    	    	{
    	    		axisSpinnerHasBeenSet(i);
    	    	}
    		}

			@Override
			public void onNothingSelected(AdapterView<?> arg0) {
				
			}
    	});*/
    	
    	xAxisSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    		public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { 
    	   // 	Spinner headerSpinner = (Spinner) findViewById(R.id.viewGraphReport_xvsySpinner);
    	    	if (myCurrentSelection != i)
    	    	{
    	    		axisSpinnerHasBeenSet(i);
    	    	}
    		}

			@Override
			public void onNothingSelected(AdapterView<?> arg0) {				
			}
    	});
    	
   /* 	yAxisSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    		public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { 
    		//	setHeaderSpinnerChoice(i);

    		}

			@Override
			public void onNothingSelected(AdapterView<?> arg0) {
				
			}
    	});
    	*/
    	categoriesSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    		public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { 
    			if (categoriesSpinner.getVisibility() == View.VISIBLE)
    			{
    				categorySpinnerHasBeenSet();
    			}
    		}

			@Override
			public void onNothingSelected(AdapterView<?> arg0) {
				
			}
    	});
    	    }
    
    /** method called when one of the spinners values is changed
     * @param the choice
     * @author SumaHarsha
     *
     */
    private void axisSpinnerHasBeenSet(int the_choice)
    {
    	Spinner xAxisSpinner = (Spinner) findViewById(R.id.viewGraphReport_xaxisSpinner);
    //	Spinner headerSpinner = (Spinner) findViewById(R.id.viewGraphReport_xvsySpinner);
    	myCurrentSelection = the_choice;
    	if (xAxisSpinner.getSelectedItemPosition() != the_choice)
    	{
    		xAxisSpinner.setSelection(the_choice);
    	}
    	/*Selse if (headerSpinner.getSelectedItemPosition() != the_choice)
    	{
    		headerSpinner.setSelection(the_choice);
    	}*/
    	
    	switch(the_choice)
    	{
    		case 0:
    			//category
    	    	if (myCategorySpending == null)
    			{
    				setCategorySpendingMap();
    			}
    	   		checkXAxisSpinner(View.INVISIBLE);
    			myBarList.setAdapter(new BarPlotListAdapter(this, myCategorySpending));
    			break;	
    			
    		case 1:
    			//subcategory
    			checkXAxisSpinner(View.VISIBLE);
    			categorySpinnerHasBeenSet();
              	break;
            	
    		case 2:
    			//date
    			if (myDateSpending == null)
    			{
    				setDateSpendingMap();
    			}
    			checkXAxisSpinner(View.INVISIBLE);
    			myBarList.setAdapter(new BarPlotListAdapter(this, myDateSpending));
               	break;
    		case 3:
    			//year
    			if (myYearSpending == null)
    			{
    				setYearSpendingMap();
    			}
    			checkXAxisSpinner(View.INVISIBLE);
    			myBarList.setAdapter(new BarPlotListAdapter(this, myYearSpending));
    			break;
    		case 4:
    			//month
    			if (myMonthSpending == null)
    			{
    				setMonthSpendingMap();
    			}
    			checkXAxisSpinner(View.INVISIBLE);
    			myBarList.setAdapter(new BarPlotListAdapter(this, myMonthSpending));
    			break;
    		case 5:
    			//day
    			if (myDaySpending == null)
    			{
    				setDaySpendingMap();
    			}
    			checkXAxisSpinner(View.INVISIBLE);
    			myBarList.setAdapter(new BarPlotListAdapter(this, myDaySpending));
    			break;    			
	
    		case 6:
    			//time
    			if (myTimeSpending == null)
    			{
    				setTimeSpendingMap();
    			}
    			checkXAxisSpinner(View.INVISIBLE);
    			myBarList.setAdapter(new BarPlotListAdapter(this, myTimeSpending));
    			break;    			
	
    		case 7:
    			if (myPaymentMethodSpending == null)
    			{
    				setPaymentMethodSpendingMap();
    			}
    			checkXAxisSpinner(View.INVISIBLE);
    			myBarList.setAdapter(new BarPlotListAdapter(this, myPaymentMethodSpending));
    			break;
    		case 8: 
    			if (mySubcategorySpending == null) 
    			{
    				setSubcategorySpendingMap();
    			}	
    			if (myAllSubcategoriesSpending == null)  
    			{
    				setAllSubcategorySpendingMap();
    			}
       			checkXAxisSpinner(View.INVISIBLE);
    			myBarList.setAdapter(new BarPlotListAdapter(this, myAllSubcategoriesSpending));
    		    break;			
    			
    			
          	default:
          		break;
    		
          		
    	}
    		
    }
    
    /** method to set categories list*/
    private void setCategories()
    {
    	myCategories = myDBInteractor.getAllSpendingCategories();
    }

        
    /** method to set category spending map*/
    private void setCategorySpendingMap()   
    {
    	if (myCategories == null)
    	{
    		setCategories();
    	}
    	if (myCategories != null)
    	{
    		myCategorySpending = new LinkedHashMap<SpendingCategory, Double>();
    		for (SpendingCategory category: myCategories)
    		{
    			if (category != null)
    			{
    	     		myCategorySpending.put(category, myDBInteractor.getTotalSpentCategory(category.getName(), 
    	     				DateTimeManager.parseForDBDate(myFromDate), DateTimeManager.parseForDBDate(myToDate)));		
    			}
    		}
    	}
    }
    
 /** method to set category spending map*/
    private void setSubcategorySpendingMap()
    {
    	if (myCategories == null)
    	{
    		setCategories();
    	}
    	if (myCategories != null)
    	{
    		mySubcategorySpending = new LinkedHashMap<String, LinkedHashMap<SpendingSubcategory, Double>>();
    		for (SpendingCategory category: myCategories)
    		{
    			if (category != null)
    			{
    	    		LinkedHashMap<SpendingSubcategory, Double> subcategoriesAmtMap = new LinkedHashMap<SpendingSubcategory, Double>();
    				List<SpendingSubcategory> subcategories = category.getSubcategories();
    				if (subcategories != null)
    				{
    					for (SpendingSubcategory subcategory: subcategories)
    					{
    						subcategoriesAmtMap.put(subcategory, myDBInteractor.getTotalSpentSubcategory(category.getName(),
    								subcategory.getName(), DateTimeManager.parseForDBDate(myFromDate), DateTimeManager.parseForDBDate(myToDate)));
    					}	
						mySubcategorySpending.put(category.getName(), subcategoriesAmtMap);	

    				}
    			}
    		}
    	}
    }
    
    
    /** method to set year spending map*/
    private void setYearSpendingMap()   
    {
    	if (myFromDate != null && myToDate != null)
    	{
    		int fromYear = getYear(myFromDate);
    		int toYear = getYear(myToDate);
    		myYearSpending = myDBInteractor.getYearWiseSpending(fromYear, toYear);
    		
    	}
    }
    
    /**
     * returns a year from string date
	 * @param myFromDate2
	 * @return int date
	 */
	private int getYear(String the_date) {
		if (the_date != null)
		{
			String[] date = the_date.split(DateTimeManager.DATESPLITTER);
			int year = Integer.parseInt(date[2]);
			return year;
		}
		return 0;
	}
    /** method to set month spending map*/
    private void setMonthSpendingMap()   
    {
    	if (myFromDate != null && myToDate != null)
    	{
    		int fromMonth = getMonth(myFromDate);
    		int toMonth = getMonth(myToDate);
    		myMonthSpending = myDBInteractor.getMonthwiseSpending(fromMonth, toMonth);
    		
    	}
    }
    /**
     * method that returns the month and year from the date
	 * @param myToDate2 date
	 * @return the month and year - yyyymm format
	 */
	private int getMonth(String the_date) {
		
		if (the_date != null)
		{
			String[] dateComps = the_date.split(DateTimeManager.DATESPLITTER);
			String month = dateComps[0].length()==1?"0".concat(dateComps[0]):dateComps[0];
			String yearMonth = dateComps[2].concat(month);
			return Integer.parseInt(yearMonth);
		}
		return 0;
	}

	/** method to set day spending map*/
    private void setDaySpendingMap()   
    {
    	if (myFromDate != null && myToDate != null)
    	{
    		myDaySpending = myDBInteractor.getDaywiseSpending(DateTimeManager.parseForDBDate(myFromDate),
    																			DateTimeManager.parseForDBDate(myToDate));
      	}
    }

	/** method to set time spending map*/
    private void setTimeSpendingMap()
    {
    	if (myFromDate != null && myToDate != null)
    	{
    		myTimeSpending = myDBInteractor.getTimewiseSpending(DateTimeManager.parseForDBDate(myFromDate),
    																			DateTimeManager.parseForDBDate(myToDate));
      	}
    }


	/** method to set payment method spending map*/
    private void setPaymentMethodSpendingMap()   
    {
    	LinkedList<PaymentMethod> paymentMethods = myDBInteractor.getAllPaymentMethods();
    	if (paymentMethods != null)
    	{
    		myPaymentMethodSpending = new LinkedHashMap<PaymentMethod, Double>();
    		for (PaymentMethod method: paymentMethods)
    		{
    			if (method != null)
    			{
    	     		myPaymentMethodSpending.put(method, myDBInteractor.getTotalSpentPaymentMethod(method.getName(), 
    	     				DateTimeManager.parseForDBDate(myFromDate), DateTimeManager.parseForDBDate(myToDate)));		
    			}
    		}
    	}
    }

    /** method to set category spending map*/
    private void setAllSubcategorySpendingMap()
    {
    	if (mySubcategorySpending == null)
    	{
    		setSubcategorySpendingMap();
    	}
    	myAllSubcategoriesSpending = new LinkedHashMap<SpendingSubcategory, Double>();
    	for (String category: mySubcategorySpending.keySet())
    	{
    		Map<SpendingSubcategory, Double> subcategoriesMap = mySubcategorySpending.get(category);
    		if (subcategoriesMap != null)
    		{
    			for (SpendingSubcategory subcategory: subcategoriesMap.keySet())
    			{
    				myAllSubcategoriesSpending.put(subcategory, subcategoriesMap.get(subcategory));
    			}
    		}
    	}
    }
    /** method to get category selected for subcategory*/
    private String getSelectedCategoryForSubcategory()
    {
    	Spinner categorySpinner = (Spinner) findViewById(R.id.viewGraphReport_categoriesSpinner);
    	String selected =  categorySpinner.getSelectedItem().toString();
    	if (selected != null)
    	{
        	return selected;

    	}
    	return null;
    }
    
  
    /**
 	 * method to populate date spending map
 	 */
 	private void setDateSpendingMap() {
 		
 		if (myFromDate != null && myToDate != null)
    	{
    		myDateSpending = myDBInteractor.getDatewiseSpending(DateTimeManager.parseForDBDate(myFromDate), DateTimeManager.parseForDBDate(myToDate));
    		
    	}
 	}
    
      
       /**Method to change from date
	 * @param the view object
	 */
	public void changeFromDate(View the_view)
	{
		DateTimeManager.changeDate(this, this, (Button) findViewById(R.id.viewGraphReport_fromDateButton));		
	}
	
	/**Method to change to date
	 * @param the view object
	 */
	public void changeToDate(View the_view)
	{
		DateTimeManager.changeDate(this, this, (Button) findViewById(R.id.viewGraphReport_toDateButton));
	}
 
	/* (non-Javadoc)
	 * @see com.bitBusy.manageyourriches.utilityClasses.pickers.DateChangeListener#dateHasChanged(android.widget.TextView)
	 */
	@Override
	public void dateHasChanged(TextView the_view) {
		if (the_view != null)
		{
			if (the_view.getId() == R.id.viewGraphReport_fromDateButton)
			{
				myFromDate = the_view.getText().toString();
			}
			else if (the_view.getId() == R.id.viewGraphReport_toDateButton)
			{
				myToDate = the_view.getText().toString();
			}
			resetAllData();			
		}
		
	}
    
    
 
	/**
     * Sets categories spinner visibility
	 * @param the value to set to
	 */
	private void checkXAxisSpinner(int the_visibility) 
	{
    	Spinner categoriesSpinner = (Spinner) findViewById(R.id.viewGraphReport_categoriesSpinner);
    	if (categoriesSpinner.getVisibility() != the_visibility)
    	{
        	Spinner mainXAxisSpinner = (Spinner) findViewById(R.id.viewGraphReport_xaxisSpinner);
        	ImageButton backButton = (ImageButton) findViewById(R.id.viewGraphReport_backButton);

    		categoriesSpinner.setVisibility(the_visibility);
			backButton.setVisibility(the_visibility);

    		if (the_visibility == View.INVISIBLE)
    		{
    			mainXAxisSpinner.setVisibility(View.VISIBLE);
    		}
    		else
    		{
    			mainXAxisSpinner.setVisibility(View.INVISIBLE);
    		}
    	}
	}


	/** method called when category spinner has been set*/
    private void categorySpinnerHasBeenSet()
    {
    	String categorySelected = getSelectedCategoryForSubcategory();
    	
    	if (mySubcategorySpending == null) 
		{
			setSubcategorySpendingMap();
		}	
    	myBarList.setAdapter(new BarPlotListAdapter(this, mySubcategorySpending.get(categorySelected)));

    }
    
    /** method to go back
     * @param the view
     */
    public void goBack(View the_view)
    {
    	Spinner xAxisSpinner = (Spinner) findViewById(R.id.viewGraphReport_xaxisSpinner);
		xAxisSpinner.setVisibility(View.VISIBLE);

    	Spinner categoriesSpinner = (Spinner) findViewById(R.id.viewGraphReport_categoriesSpinner);
    	ImageButton backButton = (ImageButton) findViewById(R.id.viewGraphReport_backButton);
    	categoriesSpinner.setVisibility(View.INVISIBLE);
    	backButton.setVisibility(View.INVISIBLE);
    	
    	axisSpinnerHasBeenSet(DEFAULTSPINNERCHOICE);


    }
  
	/** method to reset all data structures when date is changed*/
	private void resetAllData()
	{
		myCategorySpending = null;
		mySubcategorySpending = null;
		myDateSpending = null;
		myYearSpending = null;
		myMonthSpending = null;
		myDaySpending = null;
		myTimeSpending = null;
		myPaymentMethodSpending = null;
		myCategories = null;
		myAllSubcategoriesSpending = null;
		axisSpinnerHasBeenSet(myCurrentSelection);
		
		
	}
	
	 @Override
	  public boolean onCreateOptionsMenu(Menu the_menu) {
	    MenuInflater inflater = getMenuInflater();
	    inflater.inflate(R.menu.actionbar_menu, the_menu);
	    return true;
	  }
	 @Override
	  public boolean onOptionsItemSelected(MenuItem the_item) {
	    ActionBarChoice.choiceMade(this, the_item.getItemId());

	    return true;
	  }
	


	
    
     
    
}

    
